home *** CD-ROM | disk | FTP | other *** search
/ Utilities Professional 1-1500 / Utilities Professional 1-1500 (1994)(WPD)[!].iso / 12511500 / var1273.dms / var1273.adf / AmiCDROM / devsupp.c < prev    next >
C/C++ Source or Header  |  1992-09-02  |  14KB  |  499 lines

  1. /* devsupp.c:
  2.  *
  3.  * Support routines for the device handler.
  4.  * - debugging
  5.  * - Mountlist "Startup" field parsing
  6.  *
  7.  * ----------------------------------------------------------------------
  8.  * This code is (C) Copyright 1993 by Frank Munkert.
  9.  * All rights reserved.
  10.  * This software may be freely distributed and redistributed for
  11.  * non-commercial purposes, provided this notice is included.
  12.  * ----------------------------------------------------------------------
  13.  * History:
  14.  * 
  15.  * 21-Nov-93   fmu   New option SCANINTERVAL.
  16.  * 14-Nov-93   fmu   Added Handle_Control_Packet for 'cdcontrol' program.
  17.  * 10-Nov-93   fmu   New options SHOWVERSION and HFSFIRST.
  18.  * 23-Oct-93   fmu   MacHFS options added.
  19.  * 15-Oct-93   fmu   Adapted to new VOLUME structure.
  20.  */
  21.  
  22. /*
  23.  * Extract information from Mountlist "Startup" field.
  24.  */
  25.  
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <stdarg.h>
  29. #include <stdio.h>
  30.  
  31. #ifdef _DCC
  32. #define abs
  33. #endif
  34.  
  35. #include <exec/types.h>
  36. #include <clib/dos_protos.h>
  37. #include "cdrom.h"
  38. #include "device.h"
  39. #include "devsupp.h"
  40. #include "intui.h"
  41. #include "generic.h"
  42. #include "params.h"
  43. #include "cdcontrol.h"
  44.  
  45. #ifdef AZTEC_C
  46. #include <pragmas/dos_lib.h>
  47. #endif
  48. #ifdef LATTICE
  49. #include <pragmas/dos_pragmas.h>
  50. extern struct DosLibrary *DOSBase;
  51. #endif
  52. #if defined(_DCC) && defined(REGISTERED)
  53. #include <pragmas/dos_pragmas.h>
  54. extern struct Library *DOSBase;
  55. #endif
  56.  
  57. static char *TheVersion = "$VER: CDROM-Handler " VERSION;
  58.  
  59. int
  60. Get_Startup (LONG p_startup)
  61. {
  62.   enum {
  63.     ARG_DEVICE,
  64.     ARG_UNIT,
  65.     ARG_FAST,
  66.     ARG_LOWERCASE,
  67.     ARG_ROCKRIDGE,
  68.     ARG_TRACKDISK,
  69.     ARG_MACTOISO,
  70.     ARG_CONVERTSPACES,
  71.     ARG_SHOWVERSION,
  72.     ARG_HFSFIRST,
  73.     ARG_STDBUFFERS,
  74.     ARG_FILEBUFFERS,
  75.     ARG_DATAEXT,
  76.     ARG_RESOURCEEXT,
  77.     ARG_SCANINTERVAL,
  78.     ARG_PLAYCDDA,
  79.     ARGCOUNT
  80.   };
  81.  
  82.   STRPTR Args[ARGCOUNT],Index;
  83.   UBYTE LocalBuffer[100];
  84.   struct RDArgs *ArgsPtr;
  85.   int result = FALSE,len,i;
  86.  
  87.  
  88.   /* Clear the argument vector. */
  89.   memset (Args, 0, sizeof(Args));
  90.  
  91.   /* valid startup entry? */
  92.   if (!p_startup) {
  93.     Display_Error ("Filesystem startup entry invalid");
  94.     return FALSE;
  95.   }
  96.  
  97.   /* Get the contents of the startup field. */
  98.   len = ((STRPTR)(BADDR(p_startup)))[0];
  99.   if (len > sizeof (LocalBuffer) - 1)
  100.     len = sizeof (LocalBuffer) - 1;
  101.   memcpy (LocalBuffer, ((STRPTR)(BADDR(p_startup))) + 1, len);
  102.  
  103.   /* Provide null-termination. */
  104.   LocalBuffer[len] = 0;
  105.  
  106.   /* Remove leading quotes. */
  107.   for (i = 0 ; i < len ; i++) {
  108.     if (LocalBuffer[i] != ' ') {
  109.       if (LocalBuffer[i] == '\"')
  110.     LocalBuffer[i] = ' ';
  111.       break;
  112.     }
  113.   }
  114.  
  115.   /* Remove trailing quotes. */
  116.   for (i = len - 1 ; i >= 0 ; i--) {
  117.     if (LocalBuffer[i] != ' '){
  118.       if (LocalBuffer[i] == '\"')
  119.     LocalBuffer[i] = ' ';
  120.       break;
  121.     }
  122.   }
  123.  
  124.   /* Replace "-" by spaces, except "--" which is replaced by "-". */
  125.   Index = LocalBuffer;
  126.   for (i = 0 ; i < len ; i++) {
  127.     if (LocalBuffer[i] == '-') {
  128.       if (i+1 < len && LocalBuffer[i+1] == '-') {
  129.         *Index++ = '-';
  130.     i++;
  131.       } else
  132.         *Index++ = ' ';
  133.     } else
  134.       *Index++ = LocalBuffer[i];
  135.   }
  136.  
  137.   /* Provide null-termination. */
  138.   *Index = 0;
  139.  
  140.   /* Don't forget the newline, or ReadArgs won't work. */
  141.   strcat ((char *) LocalBuffer, "\n");
  142.  
  143.   if (ArgsPtr = (struct RDArgs *) AllocDosObjectTags (DOS_RDARGS,TAG_DONE)) {
  144.  
  145.     /* Don't prompt for input! */
  146.     ArgsPtr -> RDA_Flags |= RDAF_NOPROMPT;
  147.  
  148.     /* Set up for local parsing. */
  149.     ArgsPtr->RDA_Source.CS_Buffer = LocalBuffer;
  150.     ArgsPtr->RDA_Source.CS_Length = strlen ((char *) LocalBuffer);
  151.     ArgsPtr->RDA_Source.CS_CurChr = 0;
  152.  
  153.     /* Read the arguments. */
  154.     if (ReadArgs ((UBYTE *)
  155.                 "D=DEVICE,U=UNIT/N,F=FAST/S,L=LOWERCASE/S,"
  156.              "R=ROCKRIDGE/S,T=TRACKDISK/S,"
  157.           "MI=MACTOISO/S,CS=CONVERTSPACES/S,"
  158.           "SV=SHOWVERSION/S,HF=HFSFIRST/S,"
  159.           "SB=STDBUFFERS/K/N,FB=FILEBUFFERS/K/N,"
  160.           "DE=DATAEXT/K,RE=RESOURCEEXT/K,"
  161.           "SI=SCANINTERVAL/K/N,PC=PLAYCDDA/K",
  162.           (LONG *) Args, ArgsPtr)) {
  163.       result = TRUE;
  164.  
  165.       if (Args[ARG_DEVICE]) {
  166.         len = strlen((char *) (Args[ARG_DEVICE]));
  167.  
  168.         if (len >= sizeof (g_device)) {
  169.        Display_Error ("Device name entry too long");
  170.        result = FALSE;
  171.         } else
  172.       strcpy (g_device, (char *) (Args[ARG_DEVICE]));
  173.       } else
  174.         Display_Error("Device name entry missing");
  175.  
  176.       g_unit = *(long *) (Args[ARG_UNIT]);
  177.       g_fastmem = (Args[ARG_FAST] != NULL);
  178.       g_map_to_lowercase = (Args[ARG_LOWERCASE] != NULL);
  179.       g_use_rock_ridge = (Args[ARG_ROCKRIDGE] != NULL);
  180.       g_trackdisk = (Args[ARG_TRACKDISK] != NULL);
  181.       g_show_version_numbers = (Args[ARG_SHOWVERSION] != NULL);
  182.       g_hfs_first = (Args[ARG_HFSFIRST] != NULL);
  183.  
  184.       if (Args[ARG_STDBUFFERS]) {      
  185.         g_std_buffers = *(long *) (Args[ARG_STDBUFFERS]);
  186.         if (g_std_buffers <= 0) {
  187.           Display_Error ("Illegal number of standard buffers: %ld", g_std_buffers);
  188.       result = FALSE;
  189.         }
  190.       } else
  191.         g_std_buffers = 5;
  192.       
  193.       if (Args[ARG_FILEBUFFERS]) {
  194.         g_file_buffers = *(long *) (Args[ARG_FILEBUFFERS]);
  195.         if (g_file_buffers <= 0) {
  196.           Display_Error ("Illegal number of file buffers: %ld", g_std_buffers);
  197.       result = FALSE;
  198.         }
  199.       } else
  200.         g_file_buffers = 5;
  201.  
  202.       if (Args[ARG_DATAEXT])
  203.         strcpy (g_data_fork_extension, (char *) Args[ARG_DATAEXT]);
  204.  
  205.       if (Args[ARG_RESOURCEEXT])
  206.         strcpy (g_resource_fork_extension, (char *) Args[ARG_RESOURCEEXT]);
  207.  
  208.       g_convert_hfs_filenames = (Args[ARG_MACTOISO] != NULL);
  209.       g_convert_hfs_spaces = (Args[ARG_CONVERTSPACES] != NULL);
  210.  
  211.       if (Args[ARG_SCANINTERVAL]) {
  212.         g_scan_interval = *(long *) (Args[ARG_SCANINTERVAL]);
  213.         if (g_scan_interval < 0)
  214.           g_scan_interval = 0;
  215.       } else
  216.         g_scan_interval = 3;
  217.  
  218.       if (Args[ARG_PLAYCDDA]) {
  219.         len = strlen((char *) (Args[ARG_PLAYCDDA]));
  220.  
  221.         if (len >= sizeof (g_play_cdda_command)) {
  222.        Display_Error ("PLAYCDDA command name too long");
  223.        result = FALSE;
  224.         } else
  225.       strcpy (g_play_cdda_command, (char *) (Args[ARG_PLAYCDDA]));
  226.       } else
  227.         g_play_cdda_command[0] = 0;
  228.  
  229.       FreeArgs(ArgsPtr);
  230.     } else {
  231.       Fault(IoErr (), (UBYTE *) "", LocalBuffer, 100);
  232.       Display_Error ("Error while parsing \"Startup\" field in Mountlist:\n%s",
  233.                    LocalBuffer + 2);
  234.     }
  235.  
  236.     FreeDosObject (DOS_RDARGS, ArgsPtr);
  237.   } else
  238.     Display_Error ("Out of memory");
  239.  
  240.   if (result) {
  241.     if (!(g_cd = Open_CDROM (g_device, g_unit, g_trackdisk, g_fastmem,
  242.                    g_std_buffers, g_file_buffers))) {
  243.       switch (g_cdrom_errno) {
  244.       case CDROMERR_NO_MEMORY:
  245.         if (g_fastmem)
  246.           Display_Error ("Out of memory: cannot allocate buffers\n"
  247.                  "(Do not use the FAST option if have no fast memory.)");
  248.         else
  249.           Display_Error ("Out of memory: cannot allocate buffers\n"
  250.                  "(Try using the FAST option.)");
  251.         break;
  252.       case CDROMERR_MSGPORT:
  253.         Display_Error ("Cannot open the message port.");
  254.         break;
  255.       case CDROMERR_IOREQ:
  256.         Display_Error ("Cannot open the I/O request structure.");
  257.         break;
  258.       case CDROMERR_DEVICE:
  259.         Display_Error ("Cannot open \"%s\" unit %ld", g_device, (int) g_unit);
  260.         break;
  261.       default:
  262.         break;
  263.       }
  264.       result = FALSE;
  265.     }
  266.   }
  267.  
  268.   return result;
  269. }
  270.  
  271. int Handle_Control_Packet (ULONG p_type, ULONG p_par1, ULONG p_par2)
  272. {
  273.   switch (p_type) {
  274.   case CDCMD_LOWERCASE:
  275.     g_map_to_lowercase = p_par1;
  276.     break;
  277.   case CDCMD_MACTOISO:
  278.     g_convert_hfs_filenames = p_par1;
  279.     break;
  280.   case CDCMD_CONVERTSPACES:
  281.     g_convert_hfs_spaces = p_par1;
  282.     break;
  283.   case CDCMD_SHOWVERSION:
  284.     g_show_version_numbers = p_par1;
  285.     break;
  286.   case CDCMD_HFSFIRST:
  287.     g_hfs_first = p_par1;
  288.     break;
  289.   case CDCMD_DATAEXT:
  290.     strcpy (g_data_fork_extension, (char *) p_par1);
  291.     break;
  292.   case CDCMD_RESOURCEEXT:
  293.     strcpy (g_resource_fork_extension, (char *) p_par1);
  294.     break;
  295.   default:
  296.     return 999;
  297.   }
  298.   return 0;
  299. }
  300.  
  301. #if defined(NDEBUG) && defined(_DCC)
  302. void debugmain (void)
  303. {
  304. }
  305. #endif
  306.  
  307. #if !defined(NDEBUG) || defined(DEBUG_SECTORS)
  308.  
  309. char *typetostr (int ty)
  310. {
  311.     switch(ty) {
  312.     case ACTION_DIE:        return("DIE");
  313.     case ACTION_FINDUPDATE:     return("OPEN-RW");
  314.     case ACTION_FINDINPUT:    return("OPEN-OLD");
  315.     case ACTION_FINDOUTPUT:    return("OPEN-NEW");
  316.     case ACTION_READ:        return("READ");
  317.     case ACTION_WRITE:        return("WRITE");
  318.     case ACTION_END:        return("CLOSE");
  319.     case ACTION_SEEK:        return("SEEK");
  320.     case ACTION_EXAMINE_NEXT:    return("EXAMINE NEXT");
  321.     case ACTION_EXAMINE_OBJECT: return("EXAMINE OBJ");
  322.     case ACTION_INFO:        return("INFO");
  323.     case ACTION_DISK_INFO:    return("DISK INFO");
  324.     case ACTION_PARENT:     return("PARENTDIR");
  325.     case ACTION_DELETE_OBJECT:    return("DELETE");
  326.     case ACTION_CREATE_DIR:    return("CREATEDIR");
  327.     case ACTION_LOCATE_OBJECT:    return("LOCK");
  328.     case ACTION_COPY_DIR:    return("DUPLOCK");
  329.     case ACTION_FREE_LOCK:    return("FREELOCK");
  330.     case ACTION_SET_PROTECT:    return("SETPROTECT");
  331.     case ACTION_SET_COMMENT:    return("SETCOMMENT");
  332.     case ACTION_RENAME_OBJECT:    return("RENAME");
  333.     case ACTION_INHIBIT:    return("INHIBIT");
  334.     case ACTION_RENAME_DISK:    return("RENAME DISK");
  335.     case ACTION_MORE_CACHE:    return("MORE CACHE");
  336.     case ACTION_WAIT_CHAR:    return("WAIT FOR CHAR");
  337.     case ACTION_FLUSH:        return("FLUSH");
  338.     case ACTION_SCREEN_MODE:    return("SCREENMODE");
  339.     case ACTION_IS_FILESYSTEM:    return("IS_FILESYSTEM");
  340.     case ACTION_SAME_LOCK:      return("SAME_LOCK");
  341.     case ACTION_COPY_DIR_FH:    return("COPY_DIR_FH");
  342.     case ACTION_PARENT_FH:      return("PARENT_FH");
  343.     case ACTION_EXAMINE_FH:     return("EXAMINE_FH");
  344.     case ACTION_FH_FROM_LOCK:   return("FH_FROM_LOCK");
  345.     case ACTION_CURRENT_VOLUME: return("CURRENT_VOLUME");
  346.     case ACTION_USER:        return("USER");
  347.     default:            return("---------UNKNOWN-------");
  348.     }
  349. }
  350.  
  351. /*
  352.  *  DEBUGGING CODE.    You cannot make DOS library calls that access other
  353.  *  devices from within a DOS device driver because they use the same
  354.  *  message port as the driver.  If you need to make such calls you must
  355.  *  create a port and construct the DOS messages yourself.  I do not
  356.  *  do this.  To get debugging info out another PROCESS is created to which
  357.  *  debugging messages can be sent.
  358.  *
  359.  *  You want the priority of the debug process to be larger than the
  360.  *  priority of your DOS handler.  This is so if your DOS handler crashes
  361.  *  you have a better idea of where it died from the debugging messages
  362.  *  (remember that the two processes are asyncronous from each other).
  363.  */
  364.  
  365. extern void debugproc();
  366.  
  367. void dbinit (void)
  368. {
  369.     TASK *task = FindTask(NULL);
  370.  
  371.     Dback = CreatePort(NULL, 0);
  372.     CreateProc((UBYTE *) "DEV_DB", task->tc_Node.ln_Pri+1, (BPTR) (CTOB(debugproc)),
  373.                4096);
  374.     WaitPort(Dback);                    /* handshake startup    */
  375.     GetMsg(Dback);                    /* remove dummy msg     */
  376.     dbprintf("Debugger running: %s, %s\n", TheVersion+6, __TIME__);
  377. }
  378.  
  379. void dbuninit (void)
  380. {
  381.     MSG killmsg;
  382.  
  383.     if (Dbport) {
  384.     killmsg.mn_Length = 0;        /*    0 means die        */
  385.     PutMsg(Dbport,&killmsg);
  386.     WaitPort(Dback);        /*    He's dead jim!      */
  387.     GetMsg(Dback);
  388.     DeletePort(Dback);
  389.  
  390.     /*
  391.      *  Since the debug process is running at a greater priority, I
  392.      *  am pretty sure that it is guarenteed to be completely removed
  393.      *  before this task gets control again.  Still, it doesn't hurt...
  394.      */
  395.  
  396.     Delay(50);            /*    ensure he's dead    */
  397.     }
  398. }
  399.  
  400. void dbprintf (char *format, ...)
  401. {
  402.     va_list arg;
  403.     char buf[256];
  404.     MSG *msg;
  405.  
  406.     va_start (arg, format);
  407.     if (Dbport && !DBDisable) {
  408.     vsprintf (buf, format, arg);
  409.     msg = AllocMem(sizeof(MSG)+strlen(buf)+1, MEMF_PUBLIC|MEMF_CLEAR);
  410.     msg->mn_Length = strlen(buf)+1;     /*    Length NEVER 0    */
  411.     strcpy((char *) (msg+1), buf);
  412.     PutMsg(Dbport,msg);
  413.     }
  414.     va_end (arg);
  415. }
  416.  
  417. /*
  418.  *  BTW, the DOS library used by debugmain() was actually openned by
  419.  *  the device driver.    Note: DummyMsg cannot be on debugmain()'s stack
  420.  *  since debugmain() goes away on the final handshake.
  421.  */
  422.  
  423. #ifdef LATTICE
  424. void __saveds debugmain (void)
  425. #else
  426. void debugmain (void)
  427. #endif    /* LATTICE */
  428. {
  429.     MSG *msg;
  430.     short len;
  431.     void *fh;
  432. #ifdef LOG_MESSAGES
  433.     void *out;
  434. #endif
  435.  
  436.     Dbport = CreatePort(NULL, 0);
  437.     fh = (void *) Open ((UBYTE *) "con:0/0/640/100/debugwindow", 1006);
  438.     PutMsg(Dback, &DummyMsg);
  439. #ifdef LOG_MESSAGES
  440. #ifdef LOG_TO_PAR
  441.     out = (void *) Open ((UBYTE *) "PAR:", 1006);
  442. #else
  443.     out = (void *) Open ((UBYTE *) "ram:cd.log", 1006);
  444. #endif
  445. #endif
  446.     for (;;) {
  447.     WaitPort(Dbport);
  448.     msg = GetMsg(Dbport);
  449.     len = msg->mn_Length;
  450.     if (len == 0)
  451.         break;
  452.     --len;                  /*  Fix length up   */
  453.     Write((BPTR) fh, msg+1, len);
  454. #ifdef LOG_MESSAGES
  455.     Write((BPTR) out, msg+1, len);
  456. #endif
  457.     FreeMem(msg,sizeof(MSG)+len+1);
  458.     }
  459.     Close ((BPTR) fh);
  460. #ifdef LOG_MESSAGES
  461.     Close ((BPTR) out);
  462. #endif
  463.     DeletePort(Dbport);
  464.     PutMsg(Dback,&DummyMsg);          /*  Kill handshake  */
  465. }
  466.  
  467. /*
  468.  *  The assembly tag for the DOS process:  CNOP causes alignment problems
  469.  *  with the Aztec assembler for some reason.  I assume then, that the
  470.  *  alignment is unknown.  Since the BCPL conversion basically zero's the
  471.  *  lower two bits of the address the actual code may start anywhere around
  472.  *  the label....  Sigh....  (see CreatProc() above).
  473.  */
  474.  
  475. #ifdef AZTEC_C
  476.  
  477. #asm
  478.     public    _debugproc
  479.     public    _debugmain
  480.     public    _geta4        ; for small memory model
  481.  
  482.     cseg
  483.     nop
  484.     nop
  485.     nop
  486. _debugproc:
  487.     nop
  488.     nop
  489.     movem.l D2-D7/A2-A6,-(sp)
  490.     jsr    _geta4        ; for small memory model
  491.     jsr    _debugmain
  492.     movem.l (sp)+,D2-D7/A2-A6
  493.     rts
  494. #endasm
  495.  
  496. #endif /* AZTEC_C */
  497.  
  498. #endif /* !NDEBUG || DEBUG_SECTORS */
  499.